package com.my.learn.nio.netty.longConnection;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

/**
 * @author fu
 * @version 1.0
 * @description TODO
 * @date 2021-11-05 14:42
 */
public class LongClient {

    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup eventExecutors = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventExecutors).channel(NioSocketChannel.class).handler(
                    new ChannelInitializer<Channel>() {

                        @Override
                        protected void initChannel(Channel ch) throws Exception {
                            ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4))
                                    .addLast(new LengthFieldPrepender(4))
                                    .addLast(new ProtostuffEncoder())
                                    .addLast(new ProtostuffDecoder())
                                    .addLast(new IdleStateHandler(6, 3, 0, TimeUnit.SECONDS))
                                    .addLast(new ChannelInboundHandlerAdapter() {

                                        @Override
                                        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                            System.out.println(ctx.channel().remoteAddress() + ": " + msg);
//                                            Thread.sleep(11000);
//                                            ctx.channel().writeAndFlush(msg);
                                        }

                                        @Override
                                        public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                            for (int i = 0; i < 2; i++) {
                                                Thread.sleep(1000);
                                                SendModel sendModel = new SendModel();
                                                if (i % 2 == 0) {
                                                    sendModel.setType(0);
                                                    sendModel.setSize(1);
                                                } else {
                                                    sendModel.setType(1);
                                                    sendModel.setSize(2);
                                                    sendModel.setContent("你好");
                                                }
                                                System.out.println("发送信息:" + sendModel.toString());
                                                ctx.writeAndFlush(sendModel);
                                            }
                                        }

                                        @Override
                                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                                            if (evt instanceof IdleStateEvent) {
                                                IdleStateEvent event = (IdleStateEvent) evt;
                                                switch (event.state()) {
                                                    case READER_IDLE:
                                                        System.out.println("读空闲");
                                                        ctx.close();
                                                        break;
                                                    case WRITER_IDLE:
                                                        System.out.println("写空闲");
                                                        SendModel sendModel = new SendModel();
                                                        sendModel.setType(0);
                                                        sendModel.setSize(1);
                                                        sendModel.setContent("心跳包");
                                                        ctx.channel().writeAndFlush(sendModel);
                                                        break;
                                                    default:
                                                        break;
                                                }
                                                super.userEventTriggered(ctx, evt);
                                            }
                                        }

                                    });
                        }
                    }
            );

            //使用异步连接，不管成功失败都会往下执行
            ChannelFuture future = bootstrap.connect("localhost", 9999).sync();
            future.channel().closeFuture().sync();
        } finally {
            eventExecutors.shutdownGracefully().sync();
        }
    }
}
